
package com.jiangnan.utils;

import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;

/**
 *
 * @author chenliang
 * @email wschenliang@aliyun.com
 */
public class ExcelExporter {
    private static final Logger log = LoggerFactory.getLogger(ExcelExporter.class);

    public short headerColor2= HSSFColor.WHITE.index;
    public short headerColor = 13;

    protected String[] headers;

    public ExcelExporter(String[] headers) {
        this.headers = headers;
    }

    private CellStyle createHeaderStyle(Workbook wb) {
        CellStyle style = createDefaultStyle(wb);
        style.setFillForegroundColor(headerColor2);
        style.setFillPattern(CellStyle.SOLID_FOREGROUND);
        return style;
    }

    private CellStyle createDefaultStyle(Workbook wb) {
        CellStyle style = wb.createCellStyle();
        short border = 1;
        style.setBorderBottom(border);
        style.setBorderLeft(border);
        style.setBorderRight(border);
        style.setBorderTop(border);
        style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
        style.setAlignment(CellStyle.ALIGN_CENTER);
        return style;
    }

    private void createRow(Sheet sheet, CellStyle style, String[] rowData, int rowIndex) {
        int i, len = (rowData == null ? 0 : rowData.length);
        int hlen = (headers == null ? 0 : headers.length);
        if (len > hlen)
            len = hlen;
        Row row = sheet.createRow(rowIndex);
        for (i = 0; i < len; ++i) {
            Cell cell = row.createCell(i);
            cell.setCellStyle(style);
            cell.setCellValue(rowData[i] == null ? "" : rowData[i]);
        }
        for (; i < hlen; ++i) {
            Cell cell = row.createCell(i);
            cell.setCellStyle(style);
            cell.setCellValue("");
        }
    }

    private void initColumnWidth(Sheet sheet) {
        int i, len = headers == null ? 0 : headers.length;
        for (i = 0; i < len; ++i) {
            sheet.autoSizeColumn(i);
        }
    }

    private static <T extends Comparable<T>> int compareT(T o1, T o2) {
        if (o1 == null) {
            return o2 == null ? 0 : -1;
        }
        if (o2 == null) {
            return 1;
        }
        return o1.compareTo(o2);
    }

    private static Comparator<String[]> arrayComparator = (o1, o2) -> {
        if (o1 == null) {
            return o2 == null ? 0 : -1;
        }
        if (o2 == null) {
            return 1;
        }
        int len1 = o1.length, len2 = o2.length;
        int len = (len1 > len2 ? len2 : len1);
        for (int i = 0; i < len; ++i) {
            int k = compareT(o1[i], o2[i]);
            if (k != 0) {
                return k;
            }
        }
        return len1 - len2;
    };

    /**
     * @param data
     *     导入excel文件的字节数据
     * @return 导入结果的excel文件的字节数据
     * @description
     */
    public byte[] export(String sheetName, String[][] data) {
        Workbook wb = new XSSFWorkbook();
        Sheet sheet = wb.createSheet(sheetName);
        CellStyle headerStyle = createHeaderStyle(wb);
        createRow(sheet, headerStyle, headers, 0);
        if (data != null) {
            CellStyle defaultStyle = createDefaultStyle(wb);
            int row = 0, len = data.length;
            Arrays.sort(data, arrayComparator);
            while (row < len) {
                createRow(sheet, defaultStyle, data[row], ++row);
            }
        }
        initColumnWidth(sheet);
        ByteArrayOutputStream bos = null;
        try {
            bos = new ByteArrayOutputStream();
            wb.write(bos);
            return bos.toByteArray();
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            return null;
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
    }
}
